<table class="configuration table table-bordered">
    <thead>
        <tr>
            <th class="text-left" style="width: 20%">Key</th>
            <th class="text-left" style="width: 15%">Default</th>
            <th class="text-left" style="width: 10%">Type</th>
            <th class="text-left" style="width: 55%">Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><h5>table.optimizer.agg-phase-strategy</h5><br> <span class="label label-primary">Batch</span> <span class="label label-primary">Streaming</span></td>
            <td style="word-wrap: break-word;">"AUTO"</td>
            <td>String</td>
            <td>Strategy for aggregate phase. Only AUTO, TWO_PHASE or ONE_PHASE can be set.
AUTO: No special enforcer for aggregate stage. Whether to choose two stage aggregate or one stage aggregate depends on cost. 
TWO_PHASE: Enforce to use two stage aggregate which has localAggregate and globalAggregate. Note that if aggregate call does not support optimize into two phase, we will still use one stage aggregate.
ONE_PHASE: Enforce to use one stage aggregate which only has CompleteGlobalAggregate.</td>
        </tr>
        <tr>
            <td><h5>table.optimizer.bushy-join-reorder-threshold</h5><br> <span class="label label-primary">Batch</span> <span class="label label-primary">Streaming</span></td>
            <td style="word-wrap: break-word;">12</td>
            <td>Integer</td>
            <td>The maximum number of joined nodes allowed in the bushy join reorder algorithm, otherwise the left-deep join reorder algorithm will be used. The search space of bushy join reorder algorithm will increase with the increase of this threshold value, so this threshold is not recommended to be set too large. The default value is 12.</td>
        </tr>
        <tr>
            <td><h5>table.optimizer.distinct-agg.split.bucket-num</h5><br> <span class="label label-primary">Streaming</span></td>
            <td style="word-wrap: break-word;">1024</td>
            <td>Integer</td>
            <td>Configure the number of buckets when splitting distinct aggregation. The number is used in the first level aggregation to calculate a bucket key 'hash_code(distinct_key) % BUCKET_NUM' which is used as an additional group key after splitting.</td>
        </tr>
        <tr>
            <td><h5>table.optimizer.distinct-agg.split.enabled</h5><br> <span class="label label-primary">Streaming</span></td>
            <td style="word-wrap: break-word;">false</td>
            <td>Boolean</td>
            <td>Tells the optimizer whether to split distinct aggregation (e.g. COUNT(DISTINCT col), SUM(DISTINCT col)) into two level. The first aggregation is shuffled by an additional key which is calculated using the hashcode of distinct_key and number of buckets. This optimization is very useful when there is data skew in distinct aggregation and gives the ability to scale-up the job. Default is false.</td>
        </tr>
        <tr>
            <td><h5>table.optimizer.dynamic-filtering.enabled</h5><br> <span class="label label-primary">Batch</span> <span class="label label-primary">Streaming</span></td>
            <td style="word-wrap: break-word;">true</td>
            <td>Boolean</td>
            <td>When it is true, the optimizer will try to push dynamic filtering into scan table source, the irrelevant partitions or input data will be filtered to reduce scan I/O in runtime.</td>
        </tr>
        <tr>
            <td><h5>table.optimizer.join-reorder-enabled</h5><br> <span class="label label-primary">Batch</span> <span class="label label-primary">Streaming</span></td>
            <td style="word-wrap: break-word;">false</td>
            <td>Boolean</td>
            <td>Enables join reorder in optimizer. Default is disabled.</td>
        </tr>
        <tr>
            <td><h5>table.optimizer.join.broadcast-threshold</h5><br> <span class="label label-primary">Batch</span></td>
            <td style="word-wrap: break-word;">1048576</td>
            <td>Long</td>
            <td>Configures the maximum size in bytes for a table that will be broadcast to all worker nodes when performing a join. By setting this value to -1 to disable broadcasting.</td>
        </tr>
        <tr>
            <td><h5>table.optimizer.multiple-input-enabled</h5><br> <span class="label label-primary">Batch</span></td>
            <td style="word-wrap: break-word;">true</td>
            <td>Boolean</td>
            <td>When it is true, the optimizer will merge the operators with pipelined shuffling into a multiple input operator to reduce shuffling and improve performance. Default value is true.</td>
        </tr>
        <tr>
            <td><h5>table.optimizer.non-deterministic-update.strategy</h5><br> <span class="label label-primary">Streaming</span></td>
            <td style="word-wrap: break-word;">IGNORE</td>
            <td><p>Enum</p></td>
            <td>When it is `TRY_RESOLVE`, the optimizer tries to resolve the correctness issue caused by 'Non-Deterministic Updates' (NDU) in a changelog pipeline. Changelog may contain kinds of message types: Insert (I), Delete (D), Update_Before (UB), Update_After (UA). There's no NDU problem in an insert only changelog pipeline. For updates, there are  three main NDU problems:<br />1. Non-deterministic functions, include scalar, table, aggregate functions, both builtin and custom ones.<br />2. LookupJoin on an evolving source<br />3. Cdc-source carries metadata fields which are system columns, not belongs to the entity data itself.<br /><br />For the first step, the optimizer automatically enables the materialization for No.2(LookupJoin) if needed, and gives the detailed error message for No.1(Non-deterministic functions) and No.3(Cdc-source with metadata) which is relatively easier to solve by changing the SQL.<br />Default value is `IGNORE`, the optimizer does no changes.<br /><br />Possible values:<ul><li>"TRY_RESOLVE"</li><li>"IGNORE"</li></ul></td>
        </tr>
        <tr>
            <td><h5>table.optimizer.reuse-source-enabled</h5><br> <span class="label label-primary">Batch</span> <span class="label label-primary">Streaming</span></td>
            <td style="word-wrap: break-word;">true</td>
            <td>Boolean</td>
            <td>When it is true, the optimizer will try to find out duplicated table sources and reuse them. This works only when table.optimizer.reuse-sub-plan-enabled is true.</td>
        </tr>
        <tr>
            <td><h5>table.optimizer.reuse-sub-plan-enabled</h5><br> <span class="label label-primary">Batch</span> <span class="label label-primary">Streaming</span></td>
            <td style="word-wrap: break-word;">true</td>
            <td>Boolean</td>
            <td>When it is true, the optimizer will try to find out duplicated sub-plans and reuse them.</td>
        </tr>
        <tr>
            <td><h5>table.optimizer.runtime-filter.enabled</h5><br> <span class="label label-primary">Batch</span></td>
            <td style="word-wrap: break-word;">false</td>
            <td>Boolean</td>
            <td>A flag to enable or disable the runtime filter. When it is true, the optimizer will try to inject a runtime filter for eligible join.</td>
        </tr>
        <tr>
            <td><h5>table.optimizer.runtime-filter.max-build-data-size</h5><br> <span class="label label-primary">Batch</span></td>
            <td style="word-wrap: break-word;">150 mb</td>
            <td>MemorySize</td>
            <td>Max data volume threshold of the runtime filter build side. Estimated data volume needs to be under this value to try to inject runtime filter.</td>
        </tr>
        <tr>
            <td><h5>table.optimizer.runtime-filter.min-filter-ratio</h5><br> <span class="label label-primary">Batch</span></td>
            <td style="word-wrap: break-word;">0.5</td>
            <td>Double</td>
            <td>Min filter ratio threshold of the runtime filter. Estimated filter ratio needs to be over this value to try to inject runtime filter.</td>
        </tr>
        <tr>
            <td><h5>table.optimizer.runtime-filter.min-probe-data-size</h5><br> <span class="label label-primary">Batch</span></td>
            <td style="word-wrap: break-word;">10 gb</td>
            <td>MemorySize</td>
            <td>Min data volume threshold of the runtime filter probe side. Estimated data volume needs to be over this value to try to inject runtime filter.This value should be larger than <code class="highlighter-rouge">table.optimizer.runtime-filter.max-build-data-size</code>.</td>
        </tr>
        <tr>
            <td><h5>table.optimizer.source.aggregate-pushdown-enabled</h5><br> <span class="label label-primary">Batch</span></td>
            <td style="word-wrap: break-word;">true</td>
            <td>Boolean</td>
            <td>When it is true, the optimizer will push down the local aggregates into the TableSource which implements SupportsAggregatePushDown.</td>
        </tr>
        <tr>
            <td><h5>table.optimizer.source.predicate-pushdown-enabled</h5><br> <span class="label label-primary">Batch</span> <span class="label label-primary">Streaming</span></td>
            <td style="word-wrap: break-word;">true</td>
            <td>Boolean</td>
            <td>When it is true, the optimizer will push down predicates into the FilterableTableSource. Default value is true.</td>
        </tr>
        <tr>
            <td><h5>table.optimizer.source.report-statistics-enabled</h5><br> <span class="label label-primary">Batch</span> <span class="label label-primary">Streaming</span></td>
            <td style="word-wrap: break-word;">true</td>
            <td>Boolean</td>
            <td>When it is true, the optimizer will collect and use the statistics from source connectors if the source extends from SupportsStatisticReport and the statistics from catalog is UNKNOWN.Default value is true.</td>
        </tr>
        <tr>
            <td><h5>table.optimizer.sql2rel.project-merge.enabled</h5><br> <span class="label label-primary">Batch</span> <span class="label label-primary">Streaming</span></td>
            <td style="word-wrap: break-word;">false</td>
            <td>Boolean</td>
            <td>If set to true, it will merge projects when converting SqlNode to RelNode.<br />Note: it is not recommended to turn on unless you are aware of possible side effects, such as causing the output of certain non-deterministic expressions to not meet expectations(see FLINK-20887).</td>
        </tr>
    </tbody>
</table>
